package org.road0329.dlt698.axdr;

import org.road0329.dlt698.ReverseByteArrayInputStream;
import org.road0329.dlt698.ReverseByteArrayOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.ByteBuffer;

public class Apdu {
    private static Logger logger = LoggerFactory.getLogger(Apdu.class);
    private M698pdu m698pdu = null;
    private FjCAPdu fjcliapdu = null;
    private FjSApdu fjsrvapdu = null;
    private static Apdu instance = null;

    public static Apdu getInstance() {
        if (instance == null) {
            instance = new Apdu(M698pdu.getInstance());
        }
        return instance;
    }

    public M698pdu getM698pdu() {
        if (this.m698pdu != null) {
            return this.m698pdu;
        } else {
            throw new RuntimeException("m698pdu is null");
        }
    }

    public FjSApdu getFjsrvapdu() {
        if (this.fjsrvapdu != null) {
            return this.fjsrvapdu;
        } else {
            throw new RuntimeException("fjsrvapdu is null");
        }
    }

    public void setFjsrvapdu(FjSApdu fjsrvapdu) {
        this.fjsrvapdu = fjsrvapdu;
    }

    public FjCAPdu getFjcliapdu() {
        if (this.fjcliapdu != null) {
            return this.fjcliapdu;
        } else {
            throw new RuntimeException("fjcliapdu is null");
        }
    }

    public void setFjcliapdu(FjCAPdu fjcliapdu) {
        this.fjcliapdu = fjcliapdu;
    }

    public Apdu(M698pdu m698pdu) {
        this.m698pdu = m698pdu;
    }

    public M698pdu getCosemPdu() {
        if (this.m698pdu != null) {
            return this.m698pdu;
        } else {
            throw new RuntimeException("698pdu is null");
        }
    }

    public Apdu decode(byte[] bytes) throws Exception {
        ReverseByteArrayInputStream is = new ReverseByteArrayInputStream(bytes);
        int size = is.available();
        M698pdu m698pdu = new M698pdu();
        Apdu aPdu = new Apdu(m698pdu);
        if (size > 0) {
            aPdu.m698pdu.decode(is);
            logger.debug("apdu:{}", aPdu.m698pdu.toString());
            // fj data
            if (aPdu.m698pdu.getChoiceIndex() == M698pdu.Choice.GET_REQUEST
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.SET_REQUEST
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.ACTION_REQUEST
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.CONNECT_REQUEST
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.PROXY_REQUEST) {
                aPdu.fjcliapdu = new FjCAPdu();
                aPdu.fjcliapdu.decode(is);
            } else if (aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.GET_RESPONSE
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.SET_RESPONSE
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.ACTION_RESPONSE
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.CONNECT_RESPONSE
                    || aPdu.m698pdu.getChoiceIndex() ==  M698pdu.Choice.PROXY_RESPONSE) {
                aPdu.fjsrvapdu = new FjSApdu();
                aPdu.fjsrvapdu.decode(is);
            }
        }
        return aPdu;
    }

    public int encode(byte[] buffer) throws Exception {
        ReverseByteArrayOutputStream baos = new ReverseByteArrayOutputStream();
        baos.setBufIndex(buffer, buffer.length );

        return this.encodeCosemPdu(baos);
    }

    public int encodeCosemPdu(ReverseByteArrayOutputStream baos) throws Exception {
        int ret = 0;
        if (this.m698pdu != null) {
            if (this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.GET_REQUEST
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.SET_REQUEST
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.ACTION_REQUEST
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.CONNECT_REQUEST
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.PROXY_REQUEST) {
                if (this.fjcliapdu == null)
                    this.fjcliapdu = new FjCAPdu();
                ret += this.fjcliapdu.encode(baos);
            } else if (this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.GET_RESPONSE
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.SET_RESPONSE
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.ACTION_RESPONSE
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.CONNECT_RESPONSE
                    || this.m698pdu.getChoiceIndex() ==  M698pdu.Choice.PROXY_RESPONSE) {
                if (this.fjsrvapdu == null)
                    this.fjsrvapdu = new FjSApdu();
                ret += this.fjsrvapdu.encode(baos);
            }
        }
        ret += (this.m698pdu == null ? 0 : this.m698pdu.encode(baos));
        logger.debug("ret :{}", ret);
        return ret;
    }

    @Override
    public String toString() {
        if (this.m698pdu != null) {
            return "APDU:" + this.m698pdu;
        } else {
            return "APDU: is null";
        }
    }
}



